import { YForm, YItemConfig } from '../interface';

type IConfigHandlerResult = string | number | boolean | YItemConfig;

interface IConfigCompileParams {
  form: YForm;
}
interface IFunctionHandlerParams {
  form: YForm;
  formData: { [key: string]: any };
}
type IFunctionHandler = (
  params: IFunctionHandlerParams
) => Array<IConfigHandlerResult>;
export type YItemConfigTypes =
  | YItemConfig
  | IFunctionHandler
  | string
  | number
  | boolean;
/**
 * 配置信息进行编译
 * 其目的是将配置信息中的所有配置进行编译成对象
 * 例如函数进行编译出一个对象
 */
export default class ConfigCompile {
  constructor(private options: IConfigCompileParams) {}

  getForm() {
    return this.options.form;
  }

  getFormData() {
    return this.getForm().formData;
  }

  getFnParams(itemConfig: YItemConfig) {
    return {
      form: this.getForm(),
      config: itemConfig,
      formData: this.getFormData(),
    };
  }

  functionNodeHandler(handler: IFunctionHandler): Array<IConfigHandlerResult> {
    const result = handler({
      form: this.getForm(),
      formData: this.getFormData(),
    });
    return result;
  }

  handler(configs: Array<YItemConfigTypes>): Array<IConfigHandlerResult> {
    return configs.reduce(
      (total: Array<IConfigHandlerResult>, item: YItemConfigTypes) => {
        const itemType = typeof item;
        if (['string', 'number', 'boolean'].includes(itemType)) {
          total.push(item as IConfigHandlerResult);
        } else if (Array.isArray(item)) {
          const result = this.handler(item);
          return total.concat(result);
        } else if (typeof item === 'function') {
          const result = this.functionNodeHandler(item);

          return total.concat(result);
        }

        return total;
      },
      []
    );
  }
}
